import {Plugin} from "vite";
import * as cheerio from 'cheerio'
import * as babel from "@babel/core";
// 遍历
import __traverse__ from 'babel-traverse'
import {NodePath} from "@babel/traverse";
import {CallExpression, MemberExpression} from "babel-types";
import MagicString from "magic-string";
import * as fs from "fs";

let traverse
const default1 = __traverse__?.default;
if (default1) {
    traverse = default1
} else {
    traverse = __traverse__
}

/**
 * 使用vite替换BrowseVueLoader进行开发
 */
export function viteReplaceBrowseVueLoaderDev(command: 'build' | 'serve'): Plugin {
    const valPre = '__zhixin__replaceBrowseVueLoader__transform__require__'
    let count = 0
    return {
        name: 'vite-replaceBrowseVueLoader-dev',
        transformIndexHtml: {
            order: 'pre',
            handler(code, ctx) {
                let $ = cheerio.load(code)
                if(command === 'serve') {
                    $("#BrowseVueLoaderUtilsId").html("BrowseVueLoader.openVue2Tool();BrowseVueLoader.__env='__vite__type';")
                }
                let $replaceBrowseVueLoaderUtilsMain = $("#replaceBrowseVueLoaderUtilsMain");
                const dataUrl = $replaceBrowseVueLoaderUtilsMain.attr("data-url")
                $replaceBrowseVueLoaderUtilsMain.attr("src", dataUrl)
                $replaceBrowseVueLoaderUtilsMain.attr("type", "module")
                let ZhiXinBrowseVueLoaderScEl
                $('script').each((i, el) => {
                    let Nel = $(el)
                    let src = Nel.attr('src');
                    if(src) {
                        if(src.includes('ZhiXinBrowseVueLoader.umd.min.js')) {
                            ZhiXinBrowseVueLoaderScEl = Nel
                        }
                    }
                    return;
                    if ((Nel.attr('type') === 'text/x-template')) {
                        return
                    }
                    let code = Nel.html().trim();
                    if (code) {
                        const ast = babel.parse(code, {
                            sourceType: 'module',
                            configFile: false,
                        });
                        const s = new MagicString(code)
                        let count = 0;
                        traverse(ast, {
                            // BrowseVueLoader.pageToVue
                            CallExpression(ipath: NodePath<CallExpression>) {
                                const node = ipath.node;
                                const callee = node.callee;
                                const arguments2 = node.arguments;
                                if (callee.type === 'MemberExpression') {
                                    const object = callee.object
                                    const property = callee.property
                                    if (object.type === 'Identifier' && property.type === 'Identifier') {
                                        if (object.name === 'BrowseVueLoader' && property.name === 'pageToVue') {
                                            let vueContent = `<script>
export default ${code.substring(arguments2[0].start, arguments2[0].end)}
</script>

`
                                            if (arguments2.length === 2) {
                                                let arguments2Element = arguments2[1];
                                                vueContent += `<style scoped lang="less" src="${arguments2Element.value}"></style>`
                                            }
                                            count++;
                                            let VueFileName = ctx.path + '__' + (count) + '.vue'
                                            let WVueFileName = ctx.filename + '__' + (count) + '.vue'
                                            let importFileName = '__' + (count) + 'Vue'
                                            let newScript = $(`<script type='module' async defer>
import ${importFileName} from "${VueFileName}";
window.${importFileName} = ${importFileName}
</script>`)
                                            newScript.insertBefore(Nel)
                                            fs.writeFileSync(WVueFileName, vueContent)
                                            s.overwrite(node.start, node.end, `new (Vue.extend(${importFileName}))();`)
                                        }
                                    }
                                }
                            }
                        })
                        code = s.toString()
                        Nel.html(code)
                        Nel.attr("type", "module")
                        Nel.attr("defer", "defer")
                    }
                })
                if(command === 'build') {
                    $("#BrowseVueLoaderUtilsId").remove()
                    if(ZhiXinBrowseVueLoaderScEl) {
                        ZhiXinBrowseVueLoaderScEl.remove()
                    }
                }
                return $.html()
            }
        },
        transform(code, id) {
            if (/.js$|.jsx$|.ts$|.tsx$|.vue$/.test(id)) {
                code = code.replace('import __VUE_IDENTIFIER__ from "vue"', 'const __VUE_IDENTIFIER__ = Vue')
                const ast = babel.parse(code, {
                    sourceType: 'module',
                    configFile: false,
                    comments: true
                });
                const s = new MagicString(code)
                traverse(ast, {
                    Program: {
                        enter(path) {
                            const comments = path.container.comments;
                            comments.forEach(i => {
                                let value = i.value
                                if (value) {
                                    if (value.includes('export default')) {
                                        s.prepend(`throw new Error('注释中存在可被解析的，export default，需要删除，文件：${id}')\n`)
                                    }
                                    if (/import (.*?) from "(.*?)";/.test(value)) {
                                        s.prepend(`throw new Error('注释中存在可被解析的，import，导入，需要删除，文件：${id}')\n`)
                                    }
                                }
                            })
                        }
                    },
                    // 替换 BrowseVueLoader.urlFileToVueAsync---> ()=>import
                    MemberExpression(ipath: NodePath<MemberExpression>) {
                        const node = ipath.node;
                        const object = node.object
                        const property = node.property
                        if (object.type === 'Identifier' && property.type === 'Identifier') {
                            if (object.name === 'BrowseVueLoader' && property.name === 'urlFileToVueAsync') {
                                s.overwrite(node.start, node.end, '() => import')
                            }
                        }
                    },
                    CallExpression(ipath: NodePath<CallExpression>) {
                        const node = ipath.node;
                        const callee = node.callee;
                        const arguments2 = node.arguments;
                        if (callee.type === 'Identifier') {
                            if (callee?.name === 'require') { // 支持require
                                if (arguments2.length === 1) {
                                    const arg0 = arguments2[0]
                                    const value = arg0.value as string;
                                    const valName = (valPre + count++)
                                    // 显示指定就是url
                                    s.prepend(`const ${valName} = new URL("${value}", import.meta.url).href + "${value.endsWith('/')?'/':''}";\n`)
                                    s.overwrite(node.start, node.end, `${valName}`)
                                }
                            }
                        }
                    },
                })
                code = s.toString()
            }
            return code
        }
    }
}

/**

 package.json:
 {
  "name": "jm-ytz-ui",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "dev": "vite"
  },
  "keywords": [],
  "author": "思创",
  "license": "ISC",
  "type": "module",
  "devDependencies": {
    "@babel/core": "^7.25.8",
    "@types/babel-types": "^7.0.15",
    "@types/babel__core": "^7.20.5",
    "@types/babel__traverse": "^7.20.6",
    "babel-traverse": "^6.26.0",
    "babel-types": "^6.26.0",
    "cheerio": "1.0.0-rc.12",
    "chokidar": "3.5.3",
    "less": "^4.2.0",
    "magic-string": "^0.30.12",
    "vite": "5.2.6",
    "vite-plugin-vue2": "2.0.3",
    "vue-template-compiler": "2.6.12"
  }
}
 vite.config.ts:
 import {defineConfig} from 'vite' // 动态配置函数
 import {createVuePlugin} from "vite-plugin-vue2";
 import {viteReplaceBrowseVueLoaderDev} from "./vite-replace-webpack-dev/vite-replaceBrowseVueLoader-dev";
 import vitePluginLogLevel from "./vite-replace-webpack-dev/vite-plugin-logLevel";

 export default defineConfig(({command, mode, isSsrBuild, isPreview}) => {
  const VITE_BASE_API = '/ytzydbg-api'
  return {
    plugins: [
      // 处理日志
      vitePluginLogLevel(),
      createVuePlugin(),
      viteReplaceBrowseVueLoaderDev(),
    ],
    server: {
      host: true, // host: "0.0.0.0"
      port: 4444, //端口号
      proxy: {
        [VITE_BASE_API]: {
          // target: 'https://xmk.gdtz.gov.cn',
          target: 'http://192.168.196.73:9997/web',
          // target: 'https://xmk.gdtz.gov.cn/movework-web/',
          // target: 'https://xmk.gdtz.gov.cn/move-work-web',
          // target: 'https://tzxm.gd.gov.cn/movework-web',
          // target: 'http://abc.frp.xzxsrq.top:6200/web',
          // target: 'http://127.0.0.1:9528/web',
          // target: 'http://192.168.192.46:8431',
          ws: true,
          secure: false,
changeOrigin: true,
    rewrite: path => {
    let regExp = new RegExp(`^${VITE_BASE_API}`);
    return path.replace(regExp, '');
}
}
},
},
}
})



 index.html:
 <script id="BrowseVueLoaderUtilsId">

 // 开启Vue2的调试工具
 // BrowseVueLoader.openVue2Tool()
 BrowseVueLoader.version = Date.now()
 BrowseVueLoader.setLoaderCallBack((finish, url) => {
        if (finish) {
            hideLoading()
        } else {
            showLoading()
        }
    })
 BrowseVueLoader.urlFileToJs('./src/main.js')
 </script>
 <script id="replaceBrowseVueLoaderUtilsMain" data-url="./src/main.js"></script>



 */
